home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1998 April / EnigmA AMIGA RUN 26 (1998)(G.R. Edizioni)(IT)[!][issue 1998-04].iso / earkit / useful / graburl / rexx / graburl.rexx
OS/2 REXX Batch file  |  1998-03-13  |  24KB  |  704 lines

  1. /******************************************************************************
  2. *
  3. * $VER: GrabURL 1.05 (22.2.97) (c) 1996-97 Serge Emond
  4. *
  5. *******************************************************************************
  6. *
  7. * Url Types:
  8. *   F   Failed.
  9. *   Q   Queued
  10. *   R   Received
  11. *   X   Error.
  12. *   U   Unused/Unknown
  13. *
  14. ******************************************************************************/
  15.  
  16. options results
  17. options failat 100
  18. signal on break_c
  19. signal on halt
  20. signal on ioerr
  21.  
  22. PARSE ARG Arguments
  23. call Main
  24. call DoFail 0
  25.  
  26.  
  27. /********************************************************* Default Settings **/
  28.  
  29. DoDefaults:
  30.  
  31.   /* Boolean are always set by ReadArgs.. no defaults! */
  32.  
  33.   opts.Url.Count =      0                           /* Don't grab url */
  34.   opts.Depth =         -1                           /* Grab the world! */
  35.   opts.InFile =         ''                          /* Don't read files */
  36.   opts.MaxSize =        0                           /* No limit */
  37.   opts.MinSpaceLeft =   0                           /* No Checking */
  38.   opts.Pattern =        ''                          /* No Pattern Matching */
  39.   opts.SaveRoot =       'Work:Urls/'                /* Where to put files */
  40.   opts.WorkFile =       ''                          /* No WorkFile */
  41.   opts.Delay =          0   /* seconds */           /* Delay between grabs */
  42.   opts.MaxTime =        0   /* minutes */           /* Max. time to download */
  43.   opts.MaxCount =       0                           /* Max. # of file to grab */
  44.   opts.MaxBytes =       0                           /* Max. # of bytes to grab */
  45.  
  46.   /* Defaults not configurable on command-line */
  47.   
  48.   def.KeepReceived =    1   /* 1 = Keep Recd in list, 0 = Remove Them */
  49.   def.KeepFailed =      1   /* 1 = Keep Failed in list, 0 = Remove Them */
  50.   def.KeepUnused =      1   /* 1 = Keep Unused in list */
  51.   def.FollowMoved =     1   /* 1 = Grab new destination given by the server */
  52.   def.FollowTMoved =    1   /* 1 = Same as def.FollowMoved but when a */
  53.                             /* Temporary Move is issued */
  54.   def.Secure =          1   /* 1 = Save WorkFile each time it is modified */
  55.                             /* 0 = Save on exit only */
  56.   def.Accept =      '*/*'   /* We accept all types of files */
  57.   def.EMail =           ''  /* We are anonymous.. */
  58.   def.TimeZone =       300  /* Minutes to ADD to localtime to get GMT */
  59.   def.WriteBufSize = 16*1024 /* Write Buffer Size */
  60.   def.Translate = '~:[]()'  /* Characters to be translated to "_" when saving
  61.                                to disk */
  62.   def.TranslateTo = copies("_", length(def.Translate))
  63.                             /* Characters to translate to.. */
  64.  
  65.   def.TouchOldDirs =    1   /* 1 = Reset date of old directories */
  66.   
  67.   def.TempFile =    't:GrabURL.'UID /* Temporary file to use when parsing */
  68.  
  69.   def.ParsePattern = '(FTP|HTTP)://#?'  /* Just add ftp & http in the list */
  70.   
  71.   def.PasswordFile =    ''  /* File containing authentication infos */
  72.   
  73.   /* Where to find external programs */
  74.   def.Path       = ''
  75.   def.ScanHTML  = def.Path'ScanHTML'
  76.   def.GrabHTTP   = 'run <>nil: 'def.Path'GrabHTTP'
  77.   def.UrlManager = 'run <>nil: 'def.Path'UrlManager'
  78.   
  79.   /* Output information */
  80.   def.Output        = 'CONSOLE:'
  81.   def.Progress      = 1         /* 1 = Display progress in window */
  82.   def.ExitOnClose   = 0         /* 1 = Abort everything if CloseGadget
  83.                                    event.  0 = Skip current file  */
  84.  
  85.   /* ARexx Port Names */
  86.   um    = 'UM'UID
  87.   gh    = 'GH'UID
  88.   
  89. return 0
  90.  
  91. /**************************************************************** DoDefines **/
  92.  
  93. DoDefines:
  94.     UID = pragma('i')   /* Unique ID */
  95.     
  96.     if ~show('L', "rexxsupport.library") then
  97.         call AddLib("rexxsupport.library", 0, -30)
  98.     if ~show('L', "rexxdossupport.library") then
  99.         call AddLib("rexxdossupport.library", 0, -30, 0)
  100.     
  101.     opts = "Help/S,Url=U/M,Delay/N,Depth=D/N,HeaderOnly=HO/S,"
  102.     opts = opts"IfModified=IM/S,InFile=IF/K,MaxBytes=MB/N,MaxCount=MC/N,"
  103.     opts = opts"MaxSize=MS/N,MaxTime=MT/N,MinSpaceLeft=MSL/N,"
  104.     opts = opts"NoBG/S,NoDirs=ND/S,NoHRef/S,NoSrc/S,NotExists=NE/S,"
  105.     opts = opts"Pattern=P/K,Query=Q/S,Recursive=R/S,Retry/S,"
  106.     opts = opts"SaveHeaders=SH/S,SaveRoot=SR/K,WorkFile=WF/K"
  107.     
  108.     LF = '0a'x
  109.     
  110. return 0
  111.  
  112. /** Main *********************************************************************/
  113.  
  114. Main:
  115.     call DoDefines
  116.     call DoDefaults
  117.     
  118.     if ~open('l', def.Output, 'W') then do
  119.         say 'Can''t open output display'
  120.         exit(10)
  121.     end
  122.  
  123.     if Arguments = '?' then do
  124.         call Log(opts)
  125.         call DoFail 0
  126.     end
  127.  
  128.     if strip(Arguments) = '' then do
  129.         call Log("Nothing to do!")
  130.         call DoFail 10
  131.     end
  132.  
  133.     if ~ReadArgs(Arguments, opts, "opts.") then
  134.         call DoFail(10, 'Error: 'Fault(RC))
  135.     
  136.     if opts.Help then call DisplayHelp
  137.     
  138.     /* Do we have something to do? */
  139.     if (opts.Url.Count = 0) & (opts.InFile = '') & (opts.WorkFile = '') then
  140.         DoFail 0
  141.     
  142.     call DoInit
  143.     call ReadRealms
  144.  
  145.     /* ScanHTML really likes stack.. */
  146.     oldstack = pragma('s',16384)
  147.     if oldstack>16384 then call pragma('s',oldstack)
  148.     drop oldstack
  149.  
  150.     call OpenPorts
  151.     
  152.     call AddUrls
  153.         
  154.     call cmd(um, 'GetInMem')
  155.     
  156.     call TheLoop
  157.     
  158.     if ~def.KeepReceived then call cmd(um, 'KillType R')
  159.     if ~def.KeepFailed then call cmd(um, 'KillType F')
  160.     call SaveWorkFile
  161.     
  162. call DoFail 0
  163.  
  164. /** Log **********************************************************************/
  165.  
  166. Log:
  167.     PARSE ARG log_text, log_nolf
  168.     
  169.     if log_nolf=1 then call writech('l', log_text)
  170.     else call writeln('l', log_text)
  171.     
  172.     drop log_text log_nolf
  173. return 0
  174.  
  175. /** DoFail********************************************************************/
  176. break_c:
  177.     say '***BREAK'
  178.     call DoFail 10
  179. DoFail:
  180.     PARSE ARG fail.rc, fail.msg
  181.     
  182.     if fail.rc = '' then fail.rc = 0
  183.     if text_message~='' & fail.rc~=0 then call Log(fail.msg)
  184.     
  185.     if show('P', gh) then call cmd(gh, 'Quit')
  186.     if show('P', um) then call cmd(um, 'Quit')
  187.     
  188.     call close('l')
  189.     
  190. exit fail.rc
  191.  
  192. /** Display Help *************************************************************/
  193.  
  194. DisplayHelp:
  195.     call Log "Arguments (Abbrev) <arg>"
  196.     call Log "    <#> -> number"
  197.     call Log "    <s> -> string"
  198.     call Log
  199.     call Log " URL (U) <s>         Url to grab (can have multiple arguments)"
  200.     call Log " InFile (IF) <s>     Input file containing one url/line to grab"
  201.     call Log " WorkFile (WF) <s>   File to load/save urls to.  (Keeping flags)"
  202.     call Log ""
  203.     call Log " Depth (D) <#>       Level of recursion (Default: grab indefinitely)"
  204.     call Log " IfModified (IM)     Grab only files modified since last grab"
  205.     call Log " MaxCount (MC) <#>   Maximal number of file to grab"
  206.     call Log " MaxSize (MS) <#>    Maximal size a file can have in order to grab it"
  207.     call Log " MaxTime (MT) <#>    Maximal time to download in minutes"
  208.     call Log " MinSpaceLeft (MSL) <#>  Minimal space to leave on disk when grabbing"
  209.     call Log " NoBG                Don't get background images"
  210.     call Log " NoHRef              Don't get referenced files"
  211.     call Log " NoSrc               Don't get 'SRC' urls"
  212.     call Log " NotExists (NE)      Grab only if the file does not already exists on disk"
  213.     call Log " Pattern (P) <s>     AmigaDOS pattern telling which URLs to grab"
  214.     call Log " Query (Q)           Allow '?' in urls"
  215.     call Log " Recursive (R)       Collect files recursively"
  216.     call Log " Retry               Retry files that failed"
  217.     call Log ""
  218.     call Log " Delay <#>           Time to wait between each grab (seconds)"
  219.     call Log " HeaderOnly (HO)     Grab headers, not the files"
  220.     call Log " NoDir (ND)          Don't create dirs - put the file in current directory"
  221.     call Log " SaveHeaders (SH)    Save the header of each file (.HDR)"
  222.     call Log " SaveRoot (SR) <s>   Directory where to put files"
  223.     call Log ""
  224.     call Log "Please see docs for more infos."
  225.     call DoFail 0
  226.  
  227. /** cmd **********************************************************************/
  228.  
  229. /* Send a string to an ARexx port */
  230.  
  231. cmd:
  232.     PARSE ARG port, commd
  233.     
  234.     address value port
  235.     
  236.     commd
  237.     
  238.     drop port string
  239. return RC
  240.  
  241. /** DoInit - Initialize Vars *************************************************/
  242.  
  243. DoInit:
  244.     g.cnt = 0                       /* # of url we are grabbing */
  245.     g.bytes = 0                     /* # of bytes we received */
  246.     opts.TDelay = 50 * opts.Delay   /* Transform in ticks */
  247.     opts.MaxTimeS = opts.MaxTime*60 /* Transform in seconds */
  248.     call time('r')                  /* Reset the time to 0 */
  249.  
  250. return 0
  251.  
  252. /** OpenPorts ****************************************************************/
  253.  
  254. OpenPorts:
  255.     
  256.     /* Port already in use...? */
  257.     if show('P', gh) then call DoFail(10, 'Port already in use')
  258.     /* Port already in use...? */
  259.     if show('P', um) then call DoFail(10, 'Port already in use')
  260.  
  261.     /* Start GrabHTTP */
  262.     OP.cmd = def.GrabHTTP' PORT 'gh' ACCEPT 'def.Accept' WBuf 'def.WriteBufSize
  263.     address command OP.cmd
  264.     if RC ~= 0 then call DoFail(10, 'Can''t start GrabHTTP')
  265.     
  266.     OP.i=0; do forever
  267.         if show('P', gh) then break
  268.         OP.i = OP.i + 1
  269.         if OP.i = 10 then call DoFail(10, 'Can''t find GrabHTTP''s port')
  270.         call Delay(50)      /* Wait 0.2 secs (10*20/50) */
  271.     end
  272.     
  273.     /* Add '/' to SaveRoot path */
  274.     OP.test = opts.SaveRoot ~= ''
  275.     OP.test = OP.test & right(opts.SaveRoot,1) ~= ':'
  276.     OP.test = OP.test & right(opts.SaveRoot,1) ~= '/'
  277.     if OP.test then opts.SaveRoot = opts.SaveRoot'/'
  278.     drop OP.test
  279.         
  280.     /* CD to SaveRoot dir */
  281.     if cmd(gh, 'SetDir "'opts.SaveRoot'"') ~= 0 then
  282.         call DoFail(10, 'Error cd saveroot directory')
  283.     
  284.     /* Set other defaults */
  285.     call cmd(gh, 'SetMinSpaceLeft 'opts.MinSPaceLeft)
  286.     call cmd(gh, 'SetEMail 'def.EMail)
  287.     if cmd(gh, 'SetTimeZone m 'def.TimeZone) ~= 0 then
  288.         call DoFail(10, 'Error setting TimeZone')
  289.     
  290.     /* Start UrlManager */
  291.     OP.cmd = def.UrlManager || ' PORT ' || um
  292.     address command OP.cmd
  293.     if RC ~= 0 then call DoFail(10, 'Can''t start UrlManager')
  294.     
  295.     OP.i=0; do forever
  296.         if show('P', um) then break
  297.         OP.i = OP.i + 1
  298.         if OP.i = 10 then call DoFail(10, 'Can''t find UrlManager''s port')
  299.         call Delay(20)      /* Wait 0.2 secs (10*20/50) */
  300.     end
  301.     
  302.     drop OP.i OP.cmd
  303. return 0
  304.  
  305. /** AddUrls ******************************************************************/
  306.  
  307. /* Priority: CLI urls prevails on InFile, InFile on WorkFile */
  308.  
  309. AddUrls:
  310.     /* Add Urls */
  311.     if opts.Url.count ~= 0 then do i = 0 to opts.Url.count-1
  312.         
  313.         /* Simple HTTP:// checking */
  314.         if left(upper(opts.Url.i),7) ~= 'HTTP://' then iterate
  315.         
  316.         thecmd = 'AddUrl TYPE Q URL "'opts.Url.i'" DEPTH '
  317.         if opts.Recursive then thecmd = thecmd || opts.Depth
  318.         else thecmd = thecmd || '0'
  319.         
  320.         if cmd(um, thecmd) = 2 then call DoFail(10, "Error adding url")
  321.     end
  322.     drop i
  323.     
  324.     /* Add InFile */
  325.     if opts.InFile ~='' then do
  326.         thecmd = 'ReadFile FILE "'opts.InFile'" TYPE Q DEPTH '
  327.         if opts.Recursive then thecmd = thecmd || opts.Depth
  328.         else thecmd = thecmd || '0'
  329.         
  330.         if cmd(um, thecmd) ~= 0 then call DoFail(10, "Error adding InFile")
  331.     end
  332.     drop thecmd
  333.     
  334.     /* Get WorkFile */
  335.     if (opts.WorkFile ~= '') & exists(opts.WorkFile) then
  336.         call cmd(um, 'LoadFile "'opts.WorkFile'"')
  337. return 0
  338.  
  339. /** SaveWorkFile *************************************************************/
  340.  
  341. SecureWorkFile:
  342.  
  343.     /* Don't save if not secure */
  344.     if ~def.Secure then return 0
  345.  
  346. SaveWorkFile:
  347.  
  348.     /* Don't save if no workfile! 8) */
  349.     if opts.WorkFile = '' then return 0
  350.     
  351.     if cmd(um, 'SaveFile FILE "'opts.WorkFile'" FULL') ~= 0 then
  352.         call DoFail(10, "Error: Can't save workfile!?")
  353. return 0
  354.  
  355. /** Realm Stuff **************************************************************/
  356.  
  357. ReadRealms:
  358.     if def.PasswordFile='' then do
  359.         authtot=0
  360.         return 0
  361.     end
  362.     if ~open('r',def.PasswordFile,'r') then
  363.         call DoFail(20, 'Error openning password file')
  364.     rri=0
  365.     do while ~eof('r')
  366.         line = readln('r')
  367.         if line='' then iterate
  368.         if left(line,1)=';' then iterate
  369.         rri=rri+1
  370.         parse var line authr.rri':'authu.rri
  371.     end
  372.     authtot = rri
  373.     drop rri
  374. return 0
  375.  
  376. GetRealm:
  377.     PARSE ARG gr.rlm
  378.     do gri=1 to authtot
  379.         if gr.rlm = authr.gri then return authu.gri
  380.     end
  381. return ''
  382.  
  383. /** TheLoop ******************************************************************/
  384.  
  385. TheLoop:
  386.     call TheLoop2 'Q'
  387.     if opts.Retry then
  388.         call TheLoop2 'F'
  389. return 0
  390.  
  391. TheLoop2:
  392. parse arg tl.type
  393.     /* First we do 'Q'ueued urls */
  394.     j = 1; gu.lmoved = 0
  395.     do forever
  396.         if gu.lmoved = 0 then do
  397.             call cmd(um, 'Search 'j' type 'tl.type' pattern "HTTP://#?"')
  398.             i = umres
  399.  
  400.             if i=0 then break       /* No more url */
  401.  
  402.             call cmd(um, 'GetInMem');l.t=umres
  403.             call cmd(um, 'CountType "Q"');l.q=umres
  404.             call cmd(um, 'CountType "R"');l.r=umres
  405.             call cmd(um, 'CountType "F"');l.f=umres
  406.             call cmd(um, 'CountType "X"');l.x=umres
  407.             call cmd(um, 'CountType "U"');l.u=umres
  408.             pinfo=''
  409.             if tl.type='F' then pinfo='[Retrying failed] '
  410.             pinfo=pinfo||l.t' urls: 'l.q'Q, 'l.r'R'
  411.             if l.f~=0 then pinfo=pinfo', 'l.f'F'
  412.             if l.x~=0 then pinfo=pinfo', 'l.x'X'
  413.             if l.u~=0 then pinfo=pinfo', 'l.u'U'
  414.             call cmd(gh, 'SetProgressInfo "'pinfo'"')
  415.  
  416.             g.cnt = g.cnt+1
  417.             j = i+1
  418.  
  419.             if g.cnt > 1 then call Delay(opts.TDelay)
  420.         end
  421.         if i=0 then break
  422.  
  423.         gu.lmoved = 0
  424.         call GetUrl(i)
  425.         if gu.lmoved = 1 then do
  426.             call cmd(gh, 'GetHeaderString "Location:"')
  427.             if upper(left(ghres, 9)) = 'LOCATION:' then do
  428.                 newurl = strip(right(ghres, length(ghres)-10))
  429.                 call cmd(um, 'SetUrl ID 'i' URL "'newurl'"')
  430.                 drop newurl
  431.             end
  432.             else do
  433.                 gu.lmoved = 0
  434.             end
  435.         end
  436.         else do
  437.             if ((opts.MaxCount ~= 0 ) & (g.cnt >= opts.MaxCount)) then do
  438.                 call Log 'Received the maximal number of file allowed'
  439.                 return 0
  440.             end
  441.             tl.el = time('e')
  442.             if ((opts.MaxTime ~= 0) & (opts.MaxTimeS <= time('e'))) then do
  443.                 tl.el = tl.el/60
  444.                 call Log 'Downloaded 'tl.el' mins, max was 'opts.MaxTime' mins'
  445.                 return 0
  446.             end
  447.             call cmd(gh, 'GetByteRecd')
  448.             g.bytes = g.bytes + ghres
  449.             if (opts.MaxBytes ~= 0) & (g.bytes >= opts.MaxBytes) then do
  450.                 call Log 'Downloaded 'g.bytes' bytes, max was 'opts.MaxBytes' bytes'
  451.                 return 0
  452.             end
  453.         end
  454.     end
  455.  
  456. return 0
  457.  
  458. /** GetUrl *******************************************************************/
  459.  
  460. GetUrl:
  461.     PARSE ARG gu.id, gu.isfailed
  462.     
  463.     if cmd(um, 'GetURL 'gu.id) ~= 0 then return 0
  464.     gu.url = umres
  465.     if cmd(um, 'GetDepth 'gu.id) ~= 0 then return 0
  466.     gu.depth = umres
  467.     
  468.     gu.out = '['right(g.cnt, 4)'] 'gu.url
  469.     if gu.isfailed ~= '' then gu.out = gu.out' (F)'
  470.     if opts.Recursive then gu.out = gu.out' (D: 'gu.depth')'
  471.     
  472.     call Log(gu.out'...', 1)
  473.     
  474.     if upper(left(gu.url,7)) ~= "HTTP://" then do
  475.         call Log ' Not HTTP'
  476.         if def.KeepUnused then call cmd(um, 'SetType 'gu.id' U')
  477.         else call cmd(um, 'KillUrl 'hu.id)
  478.         if def.Secure then call SecureWorkFile
  479.         return 0
  480.     end
  481.     
  482.     /* Separate host & path */
  483.     parse var gu.url shit '://' gu.hp '/' gu.path
  484.  
  485.     if gu.hp = '' then do
  486.         call Log ' Not grabbed'
  487.         if def.KeepUnused then call cmd(um, 'SetType 'gu.id' U')
  488.         else call cmd(um, 'KillUrl 'hu.id)
  489.         if def.Secure then call SecureWorkFile
  490.         return 0
  491.     end
  492.     
  493.     /* Separate host & port */
  494.     parse var gu.hp gu.host ':' gu.port
  495.     
  496.     if gu.host = '' then do
  497.         call Log ' Not grabbed'
  498.         if def.KeepUnused then call cmd(um, 'SetType 'gu.id' U')
  499.         else call cmd(um, 'KillUrl 'hu.id)
  500.         if def.Secure then call SecureWorkFile
  501.         return 0
  502.     end
  503.     if gu.port = '' then gu.port = 80
  504.     
  505.     /* Complete the name */
  506.     if gu.path = '' then gu.path = 'index.html'
  507.     else if right(gu.path, 1) = '/' then gu.path = gu.path || 'index.html'
  508.     
  509.     /* Strip path if nodirs */
  510.     if opts.NoDirs then do while index(gu.path, '/') ~= 0
  511.         gu.path = right(gu.path, length(gu.path) - index(gu.path, '/'))
  512.     end
  513.     else gu.path = gu.host'/'gu.path
  514.  
  515.     /* Translates the filename */
  516.     if def.Translate ~= '' then do
  517.         call cmd(gh, 'Translate "'gu.path'" "'def.Translate'" "'def.TranslateTo'"')
  518.         gu.path = GHRES
  519.     end
  520.  
  521.     /* Check if it already exists */
  522.     if opts.NotExists & Exists(opts.SaveRoot||gu.path) then do
  523.         call Log ' Already on disk'
  524.         if def.KeepReceived then call cmd(um, 'SetType 'gu.id' R')
  525.         else call cmd(um, 'KillUrl 'hu.id)
  526.         if def.Secure then call SecureWorkFile
  527.         return 0
  528.     end
  529.  
  530.     thecmd = 'GetHTTPFile "'gu.url'"'
  531.     if def.Progress then thecmd = thecmd' Progress'
  532.     if ~opts.NoDirs then thecmd = thecmd' FileName "'gu.path'"'
  533.     if opts.MaxSize ~= 0 then thecmd = thecmd' MaxSize 'opts.MaxSize
  534.     if opts.SaveHeaders then thecmd = thecmd' SaveHeader'
  535.     if opts.IfModified then thecmd = thecmd' IfModified'
  536.     if opts.HeaderOnly then thecmd = thecmd' HeaderOnly'
  537.     if def.TouchOldDirs then thecmd = thecmd' TouchDirs'
  538.  
  539.     call cmd(gh, thecmd)
  540.     gu.res = ghres
  541.  
  542.     /* Authorization Check */
  543.     if gu.res = '100' then do
  544.         call cmd(gh, 'GetHeaderString "HTTP/1."')
  545.         parse var ghres dummy" "h.code" "h.msg
  546.         if h.code = '401' then do
  547.             call Log(' [Auth]', 1)
  548.             call cmd(gh, 'GetHeaderString "WWW-Authenticate: Basic "')
  549.             if RC=0 then do
  550.                 parse var ghres dummy '"'g.realm'"'
  551.                 g.authpwd = GetRealm(g.realm)
  552.                 if g.authpwd = '' then do
  553.                     call Log(' Unknown realm: "'g.realm'"', 1)
  554.                     gu.res = 9999
  555.                 end
  556.                 else do
  557.                     call cmd(gh, 'SetAuth "'g.authpwd'"')
  558.                     if RC~=0 then call DoFail(20, "Error: can't alloc mem for authentication!")
  559.                     call cmd(gh, thecmd)
  560.                     gu.res = ghres
  561.                     call cmd(gh, 'SetAuth')
  562.                 end
  563.             end
  564.             else do
  565.                 call Log(' Unknown authentication method!')
  566.                 gh.res = 9999
  567.             end
  568.         end
  569.     end
  570.  
  571.     if gu.res = '0' then do
  572.         if def.KeepReceived then call cmd(um, 'SetType 'gu.id' R')
  573.         else call cmd(um, 'KillUrl 'hu.id)
  574.         call Log(' Done.', 1)
  575.         end
  576.     else if gu.res = '200' then do
  577.         call cmd(um, 'SetType 'gu.id' F')
  578.         call Log(' Incomplete file.', 1)
  579.     end
  580.     else if gu.res = '9999' then nop
  581.     else if gu.res = '100' then do
  582.         call cmd(gh, 'GetHeaderString "HTTP/1."')
  583.         parse var ghres dummy" "h.code" "h.msg
  584.         if h.code = '304' then do
  585.             call Log(' Not modified.', 1)
  586.             if def.KeepReceived then call cmd(um, 'SetType 'gu.id' R')
  587.             else call cmd(um, 'KillUrl 'hu.id)
  588.             end
  589.         else if h.code = '301' then do
  590.             call Log(' Moved.', 1)
  591.             if def.FollowMoved = '1' then gu.lmoved = 1
  592.             else if def.FollowMoved = 'F' then call cmd(um, 'SetType 'gu.id' F')
  593.             else if def.FollowMoved = 'X' then call cmd(um, 'SetType 'gu.id' X')
  594.             end
  595.         else if h.code = '302' then do
  596.             call Log(' Moved temporarily.', 1)
  597. /*            if def.KeepReceived then call cmd(um, 'SetType 'gu.id' F') */
  598. /*            else call cmd(um, 'KillUrl 'hu.id) */
  599.             if def.FollowTMoved = '1' then gu.lmoved = 1
  600.             else if def.FollowTMoved = 'F' then call cmd(um, 'SetType 'gu.id' F')
  601.             else if def.FollowTMoved = 'X' then call cmd(um, 'SetType 'gu.id' X')
  602.             end
  603.         else if h.code = '401' then do
  604.             call Log(' Bad user/password.', 1)
  605.             call cmd(um, 'SetType 'gu.id' U')
  606.             end
  607.         else do
  608.             call Log(' 'h.code' 'h.msg'.', 1)
  609.             if def.KeepReceived then call cmd(um, 'SetType 'gu.id' X')
  610.             else call cmd(um, 'KillUrl 'hu.id)
  611.             end
  612.         end
  613.     else if gu.res='104' then do
  614.         call Log(' Host not found.', 1)
  615.         call cmd(um, 'SetType 'gu.id' X')
  616.     end
  617.     else if gu.res='107' then do
  618.         call Log(' Disk Full.', 1)
  619.         call DoFail(20, "Error Disk Full.")
  620.     end
  621.     else if gu.res='200' then do
  622.         call Log(' File incomplete.', 1)
  623.         call cmd(um, 'SetType 'gu.id' F')
  624.     end
  625.     else if gu.res='201' then do
  626.         call Log(' Stopped by user.', 1)
  627.         call cmd(um, 'SetType 'gu.id' F')
  628.     end
  629.     else if gu.res='202' then do
  630.         call Log(' Aborted by user.')
  631.         call DoFail(10, "Error: User abort.")
  632.     end
  633.     else if gu.res='97' then do
  634.         call Log(' Failed to create socket.', 1)
  635.         call DoFail(20, "Error.")
  636.     end
  637.     else if (gu.res='98') | (gu.res='99') | (gu.res='164') then do
  638.         call Log(' Not enough memory.', 1)
  639.         call DoFail(20, "Error.")
  640.     end
  641.     else do
  642.         call Log(' Failed code 'gu.res'.', 1)
  643.         if def.KeepFailed then call cmd(um, 'SetType 'gu.id' F')
  644.         else call cmd(um, 'KillUrl 'hu.id)
  645.     end
  646.  
  647.     if gu.res == '0' & opts.Recursive then do
  648.         call cmd(gh, 'GetHeaderString "Content-Type:"')
  649.         if (index(upper(ghres), 'TEXT/HTML')~=0) | (index(upper(gu.path), '.HTM') > (length(gu.path)-5)) then do
  650.             if gu.depth ~= 0 then do
  651.                 if gu.depth = -1 then gu.newdepth = -1
  652.                 else gu.newdepth = gu.depth - 1
  653.  
  654.                 thecmd = def.ScanHTML' "'opts.SaveRoot||gu.path'" "'def.TempFile'"'
  655.                 thecmd = thecmd' Base "'gu.url'" Pattern2 "'def.ParsePattern'" Strip# NoF# NoQuery'
  656.                 if opts.Pattern ~= '' then thecmd = thecmd' Pattern "'opts.Pattern'"'
  657.                 if opts.NoSrc then thecmd = thecmd' NoSrc'
  658.                 if opts.NoHRef then thecmd = thecmd' NoHRef'
  659.                 if opts.NoBG then thecmd = thecmd' NoBG'
  660.  
  661.                 address command thecmd
  662.                 if RC ~= 0 then call Log ' (Can''t parse)'
  663.                 else do
  664.                     if cmd(um, 'ReadFile 'def.TempFile' Q Depth 'gu.newdepth) ~= 0 then do
  665.                         call Log ' (Can''t add urls)'
  666.                     end
  667.                     else do
  668.                         if umres = '0' then call Log ''
  669.                         else if umres = '1' then
  670.                             call Log ' (+1 url)'
  671.                         else call Log ' (+'umres' urls)'
  672.                     end
  673.                 end
  674.                 call Delete(def.TempFile)
  675.             end
  676.             else call Log
  677.         end
  678.         else call Log
  679.     end
  680.     else call Log ''
  681.  
  682.     call SecureWorkFile
  683.  
  684. return 0
  685.  
  686. novalue:
  687.     call oops("Novalue", sigl)
  688. syntax:
  689.     call oops("Syntax(RC="RC")", sigl, RC)
  690. failure:
  691.     call oops("Failure(RC="RC")", sigl)
  692. ioerr:
  693.     call oops("IOErr", sigl)
  694. halt:
  695.     call oops("Halt", sigl)
  696. error:
  697.     call oops("Error", sigl)
  698. oops:
  699.     parse arg what, badline, code
  700.     if code != '' then
  701.         call DoFail(40, "ERR: Line "badline what errortext(code))
  702.     else
  703.         call DoFail(40, "ERR: Line "badline what)
  704.